// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //
//
//  Project:   Talina Gaming System (TgS) (∂)
//  File:      TgS Collision - External [Main].cpp
//  Author:    Andrew Aye (EMail: andrew.aye@gmail.com, Web: http://www.andrewaye.com) 
//  Version:   3.11
//
// ------------------------------------------------------------------------------------------------------------------------------ //
//
//  Copyright: © 2002-2008, Andrew Aye.  All Rights Reserved.
//
//  This software is free for non-commercial use. Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met: 
//    Redistributions of source code must retain this copyright notice, this list of conditions and the following disclaimers. 
//    Redistributions in binary form must reproduce this copyright notice, this list of conditions and the following
//      disclaimers in the documentation and other materials provided with the distribution. 
//
//  Neither the names of the copyright owner nor the names of its contributors may be used to endorse or promote products derived
//  from this software without specific prior written permission. 
//
//  The intellectual property rights of the algorithms used reside with Andrew Aye.  You may not use this software, in whole or
//  in part, in support of any commercial product without the express written consent of the author.
//
//  There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //

// ============================================================================================================================== //

//   Large switch statements are known to be particularly bad on the in-order CPUs in the current consoles.  However, all other
//  methods would be equivalent.  Possible solutions that were debated (not tested): (1) Function pointers - this would require
//  the retrieval of the pointer and then a jump to the function.  Since jumps are near-equivalent to a branch, nothing is gained.
//  (2) Virtual tables - at a compiler/machine level this is the same as (1).  

// ============================================================================================================================== //




namespace TGS { // START TGS ///////////////////////////////////////////////////////////////////////////////////////////////////////
namespace COL { // START COL ///////////////////////////////////////////////////////////////////////////////////////////////////////


template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_BSP;
template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_BVT;
template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_PVS;
template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_Part;
template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_Primitive;
template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_TriList;
template <typename TYPE, int DIM> TgUINT32 TTgCOL_PACKET<TYPE,DIM>::m_uiStat_Tri;

// ============================================================================================================================== //
// -- Collision Queries --------------------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

template <typename TYPE, int DIM>
TgBOOL TTgCOL_PACKET<TYPE,DIM>::Trivial_Check( CR_(SPHERE,DIM) tgSP )
{
    switch (Query_Primitive() + (m_uiTest << 16)) {

    case ETgPARTICLE + (ETgTEST_INTERSECT << 16):       return (F_Contact_Test( m_tgAABB, tgSP ));

    case ETgLINE + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( tgSP, m_tgLN ));
    case ETgRAY + (ETgTEST_INTERSECT << 16):            return (F_Contact_Test( tgSP, m_tgRY ));
    case ETgSEGMENT + (ETgTEST_INTERSECT << 16):        return (F_Contact_Test( tgSP, m_tgSG ));

    case ETgCIRCLE + (ETgTEST_INTERSECT << 16):         return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgDISK + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgELLIPSE + (ETgTEST_INTERSECT << 16):        return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgPTRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgETRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgCTRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgSTRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgRECTANGLE + (ETgTEST_INTERSECT << 16):      return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgPARALLELOGRAM + (ETgTEST_INTERSECT << 16):  return (F_Contact_Test( m_tgAABB, tgSP ));

    case ETgSPHERE + (ETgTEST_SWEEP_PENETRATE << 16):   return (F_Contact_Test( m_tgSP, tgSP, m_tgDT.m_tvUDT, m_tgDT.m_tyDT ));
    case ETgSPHERE + (ETgTEST_SWEEP << 16):             return (F_Contact_Test( m_tgSP, tgSP, m_tgDT.m_tvUDT, m_tgDT.m_tyDT ));
    case ETgSPHERE + (ETgTEST_INTERSECT << 16):         return (F_Contact_Test( m_tgSP, tgSP ));
    case ETgBOX + (ETgTEST_INTERSECT << 16):            return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgBOXAA + (ETgTEST_INTERSECT << 16):          return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgCAPSULE + (ETgTEST_INTERSECT << 16):        return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgCYLINDER + (ETgTEST_INTERSECT << 16):       return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgMESH_AABB + (ETgTEST_INTERSECT << 16):      return (F_Contact_Test( m_tgAABB, tgSP ));
    case ETgMESH_BVT + (ETgTEST_INTERSECT << 16):       return (F_Contact_Test( m_tgAABB, tgSP ));

    default: TgASSERT( TgFALSE ); return (TgFALSE);

    };
};

template <typename TYPE, int DIM>
TgBOOL TTgCOL_PACKET<TYPE,DIM>::Trivial_Check( CR_(BOXAA,DIM) tgBA )
{
    switch (Query_Primitive() + (m_uiTest << 16)) {

    case ETgPARTICLE + (ETgTEST_INTERSECT << 16):       return (F_Contact_Test( m_tgAABB, tgBA ));

    //case ETgLINE + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( tgBA, m_tgLN ));
    //case ETgRAY + (ETgTEST_INTERSECT << 16):            return (F_Contact_Test( tgBA, m_tgRY ));
    //case ETgSEGMENT + (ETgTEST_INTERSECT << 16):        return (F_Contact_Test( tgBA, m_tgSG ));

    case ETgCIRCLE + (ETgTEST_INTERSECT << 16):         return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgDISK + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgELLIPSE + (ETgTEST_INTERSECT << 16):        return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgPTRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgETRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgCTRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgSTRI + (ETgTEST_INTERSECT << 16):           return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgRECTANGLE + (ETgTEST_INTERSECT << 16):      return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgPARALLELOGRAM + (ETgTEST_INTERSECT << 16):  return (F_Contact_Test( m_tgAABB, tgBA ));

    case ETgSPHERE + (ETgTEST_SWEEP_PENETRATE << 16):   return (F_Contact_Test( m_tgAABB, tgBA, m_tgDT.m_tvDT ));
    case ETgSPHERE + (ETgTEST_SWEEP << 16):             return (F_Contact_Test( m_tgAABB, tgBA, m_tgDT.m_tvDT ));
    case ETgSPHERE + (ETgTEST_INTERSECT << 16):         return (F_Contact_Test( tgBA, m_tgSP ));
    case ETgBOX + (ETgTEST_INTERSECT << 16):            return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgBOXAA + (ETgTEST_INTERSECT << 16):          return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgCAPSULE + (ETgTEST_INTERSECT << 16):        return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgCYLINDER + (ETgTEST_INTERSECT << 16):       return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgMESH_AABB + (ETgTEST_INTERSECT << 16):      return (F_Contact_Test( m_tgAABB, tgBA ));
    case ETgMESH_BVT + (ETgTEST_INTERSECT << 16):       return (F_Contact_Test( m_tgAABB, tgBA ));

    default: TgASSERT( TgFALSE ); return (TgFALSE);

    };
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(PARTICLE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(LINE,DIM) tgLN )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

    //case ETgBOXAA + (ETgTEST_BOOLEAN << 16):            F_Contact_Test( m_tgBA, tgLN ); break;
    case ETgCAPSULE + (ETgTEST_BOOLEAN << 16):          F_Contact_Test( m_tgCP, tgLN ); break;
    //case ETgCYLINDER + (ETgTEST_BOOLEAN << 16):         F_Contact_Test( m_tgCY, tgLN ); break;
    case ETgPARALLELOGRAM + (ETgTEST_BOOLEAN << 16):    F_Contact_Test( m_tgPE, tgLN ); break;
    case ETgLINE + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgLN, tgLN ); break;
    case ETgRAY + (ETgTEST_BOOLEAN << 16):              F_Contact_Test( m_tgRY, tgLN ); break;
    case ETgSEGMENT + (ETgTEST_BOOLEAN << 16):          F_Contact_Test( m_tgSG, tgLN ); break;
    case ETgPLANE + (ETgTEST_BOOLEAN << 16):            F_Contact_Test( m_tgPN, tgLN ); break;
    case ETgRECTANGLE + (ETgTEST_BOOLEAN << 16):        F_Contact_Test( m_tgRT, tgLN ); break;
    case ETgSPHERE + (ETgTEST_BOOLEAN << 16):           F_Contact_Test( m_tgSP, tgLN ); break;
    case ETgETRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgET, tgLN ); break;
    case ETgCTRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgCT.Query_ET(), tgLN ); break;
    case ETgSTRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgST.Query_ET(), tgLN ); break;

    case ETgETRI + (ETgTEST_INTERSECT << 16):           F_Contact_Intersect( &m_tgPacket, m_tgET, tgLN ); break;
    case ETgCTRI + (ETgTEST_INTERSECT << 16):           F_Contact_Intersect( &m_tgPacket, m_tgCT.Query_ET(), tgLN ); break;
    case ETgSTRI + (ETgTEST_INTERSECT << 16):           F_Contact_Intersect( &m_tgPacket, m_tgST.Query_ET(), tgLN ); break;
    case ETgSPHERE + (ETgTEST_INTERSECT << 16):         F_Contact_Intersect( &m_tgPacket, m_tgSP, tgLN ); break;
    case ETgCAPSULE + (ETgTEST_INTERSECT << 16):        F_Contact_Intersect( &m_tgPacket, m_tgCP, tgLN ); break;
    case ETgCYLINDER + (ETgTEST_INTERSECT << 16):       F_Contact_Intersect( &m_tgPacket, m_tgCY, tgLN ); break;

    default: TgASSERT( TgFALSE ); return (TgE_FAIL);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(RAY,DIM) tgRY )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

    //case ETgBOXAA + (ETgTEST_BOOLEAN << 16):            F_Contact_Test( m_tgBA, tgRY ); break;
    case ETgCAPSULE + (ETgTEST_BOOLEAN << 16):          F_Contact_Test( m_tgCP, tgRY ); break;
    //case ETgCYLINDER + (ETgTEST_BOOLEAN << 16):         F_Contact_Test( m_tgCY, tgRY ); break;
    case ETgPARALLELOGRAM + (ETgTEST_BOOLEAN << 16):    F_Contact_Test( m_tgPE, tgRY ); break;
    case ETgLINE + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgLN, tgRY ); break;
    case ETgRAY + (ETgTEST_BOOLEAN << 16):              F_Contact_Test( m_tgRY, tgRY ); break;
    case ETgSEGMENT + (ETgTEST_BOOLEAN << 16):          F_Contact_Test( m_tgSG, tgRY ); break;
    case ETgPLANE + (ETgTEST_BOOLEAN << 16):            F_Contact_Test( m_tgPN, tgRY ); break;
    case ETgRECTANGLE + (ETgTEST_BOOLEAN << 16):        F_Contact_Test( m_tgRT, tgRY ); break;
    case ETgSPHERE + (ETgTEST_BOOLEAN << 16):           F_Contact_Test( m_tgSP, tgRY ); break;
    case ETgETRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgET, tgRY ); break;
    case ETgCTRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgCT.Query_ET(), tgRY ); break;
    case ETgSTRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgST.Query_ET(), tgRY ); break;

    default: TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(SEGMENT,DIM) tgSG )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

    //case ETgBOXAA + (ETgTEST_BOOLEAN << 16):            F_Contact_Test( m_tgBA, tgSG ); break;
    case ETgCAPSULE + (ETgTEST_BOOLEAN << 16):          F_Contact_Test( m_tgCP, tgSG ); break;
    //case ETgCYLINDER + (ETgTEST_BOOLEAN << 16):         F_Contact_Test( m_tgCY, tgSG ); break;
    case ETgPARALLELOGRAM + (ETgTEST_BOOLEAN << 16):    F_Contact_Test( m_tgPE, tgSG ); break;
    case ETgLINE + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgLN, tgSG ); break;
    case ETgRAY + (ETgTEST_BOOLEAN << 16):              F_Contact_Test( m_tgRY, tgSG ); break;
    case ETgSEGMENT + (ETgTEST_BOOLEAN << 16):          F_Contact_Test( m_tgSG, tgSG ); break;
    case ETgPLANE + (ETgTEST_BOOLEAN << 16):            F_Contact_Test( m_tgPN, tgSG ); break;
    case ETgRECTANGLE + (ETgTEST_BOOLEAN << 16):        F_Contact_Test( m_tgRT, tgSG ); break;
    case ETgSPHERE + (ETgTEST_BOOLEAN << 16):           F_Contact_Test( m_tgSP, tgSG ); break;
    case ETgETRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgET, tgSG ); break;
    case ETgCTRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgCT.Query_ET(), tgSG ); break;
    case ETgSTRI + (ETgTEST_BOOLEAN << 16):             F_Contact_Test( m_tgST.Query_ET(), tgSG ); break;

    default: TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(CIRCLE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(DISK,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(ELLIPSE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(PLANE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(PTRI,DIM) tgPT )
{
    if (!F_Contact_Test( m_tgAABB, tgPT ))
    {
        return (TgE_NOINTERSECT);
    };

    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(ETRI,DIM) tgET )
{
    if (!F_Contact_Test( m_tgAABB, tgET.Query_PT() ))
    {
        return (TgE_NOINTERSECT);
    };

    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(CTRI,DIM) tgCT )
{
    if (!F_Contact_Test( m_tgAABB, tgCT.Query_PT() ))
    {
        return (TgE_NOINTERSECT);
    };

    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(STRI,DIM) tgST )
{
    if (!F_Contact_Test( m_tgAABB, tgST.Query_PT() ))
    {
        return (TgE_NOINTERSECT);
    };

    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(RECTANGLE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(PARALLELOGRAM,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(SPHERE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(BOX,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(BOXAA,DIM) tgBA )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(CAPSULE,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(CYLINDER,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Test( CR_(MESH_AABB,DIM) )
{
    m_tgPacket.m_niContact = 0;

    switch (Query_Primitive() + (m_uiTest << 16)) {

        case 0:     TgASSERT( TgFALSE ); return (TgFALSE);
        default:    TgASSERT( TgFALSE ); return (TgFALSE);

    };

    return (Process_Contact_Packet( m_tgPacket ));
};

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Process_Contact_Packet( CR_(CONTACT_PACKET,DIM) )
{
    return (TgE_FAIL);
};


// ============================================================================================================================== //
// -- Initilization and Setup --------------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

// ---- Constructor ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Constructor()
{
    m_uiPrimitive = ETgPRIMITIVE_UNKNOWN;
    Set_OwnsData( TgFALSE );
};


// ---- Reset ------------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Reset()
{
    Primitive_Reset(); //« If a primitive did exist, have it release all allocated memory

    m_tgContext.Reset();

    m_uiPrimitive = ETgPRIMITIVE_UNKNOWN;
    m_uiTest = ETgTEST_UNKNOWN;
    m_uiPurpose = ETgPURPOSE_UNDEFINED;
    m_uiFilter_Objects = 0;

    m_ptgMainObject = NULL;
    m_tgAABB.Reset();
    m_bfFlags.Reset();

    m_niObject_Graph_Ignored = 0;
    m_niObject_Ignored = 0;
    m_niLiteral_Ignored = 0;

    m_tyToI = TYPE(0.0);

    m_tgDT.m_tvUDT = MATH::F_0<TYPE,DIM>();
    m_tgDT.m_tvDT = MATH::F_0<TYPE,DIM>();
    m_tgDT.m_tyDT = TYPE(0.0);
    m_tgDT.m_tyDT_DT = TYPE(0.0);
    m_tgDT.m_tyInv_DT = TYPE(0.0);

    m_tgPacket.m_ptgContact = m_atgContact;
    m_tgPacket.m_tySweepTol = LIMITS<TYPE>::ROOTEPSILON;
    m_tgPacket.m_tySnapTol = LIMITS<TYPE>::EPSILON;
    m_tgPacket.m_niContact = 0;
    m_tgPacket.m_niMaxContact = 8;
    m_tgPacket.m_iStride = sizeof(T_(CONTACT,DIM));

    m_ptgResult = m_atgInternal_Result;
    m_niResult_Last = 0;
    m_niResult_End = KTgMaxInternal;
};


// ---- Set_Visual_Tool --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Set_Visual_Tool()
{

};


// ---- Is_Valid ----------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgBOOL TTgCOL_PACKET<TYPE,DIM>::Is_Valid() const
{
    switch (Query_Primitive())
    {
        case ETgPARTICLE:       return (m_tgPC.Is_Valid());

        case ETgLINE:           return (m_tgLN.Is_Valid());
        case ETgRAY:            return (m_tgRY.Is_Valid());
        case ETgSEGMENT:        return (m_tgSG.Is_Valid());

        case ETgCIRCLE:         return (m_tgCI.Is_Valid());
        case ETgDISK:           return (m_tgDK.Is_Valid());
        case ETgELLIPSE:        return (m_tgEL.Is_Valid());
        case ETgPTRI:           return (m_tgPT.Is_Valid());
        case ETgETRI:           return (m_tgET.Is_Valid());
        case ETgCTRI:           return (m_tgCT.Is_Valid());
        case ETgSTRI:           return (m_tgST.Is_Valid());
        case ETgRECTANGLE:      return (m_tgRT.Is_Valid());
        case ETgPARALLELOGRAM:  return (m_tgPE.Is_Valid());

        case ETgSPHERE:         return (m_tgSP.Is_Valid());
        case ETgBOX:            return (m_tgBX.Is_Valid());
        case ETgBOXAA:          return (m_tgBA.Is_Valid());
        case ETgCAPSULE:        return (m_tgCP.Is_Valid());
        case ETgCYLINDER:       return (m_tgCY.Is_Valid());
        case ETgMESH_AABB:      return (m_tgMH.Is_Valid());
        case ETgMESH_BVT:       return (m_tgMH.Is_Valid());

        default:                TgASSERT( TgFALSE ); return (TgFALSE);
    };
};


// ---- NEW_Packet -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
PC_(COL_PACKET,DIM) TTgCOL_PACKET<TYPE,DIM>::New_Packet()
{
    PC_(COL_PACKET,DIM) ptgPacket = TgNEW TTgCOL_PACKET();
    ptgPacket->Constructor();

    return (ptgPacket);
};


// ---- NEW_Duplicate_Packet ---------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
PC_(COL_PACKET,DIM) TTgCOL_PACKET<TYPE,DIM>::New_Packet( CR_(COL_PACKET,DIM) tgPacket )
{
    PC_(COL_PACKET,DIM) ptgPacket = New_Packet();
    ptgPacket->Set( tgPacket );

    return (ptgPacket);
};


// ---- NEW_Transform_Packet ---------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
PC_(COL_PACKET,DIM) TTgCOL_PACKET<TYPE,DIM>::New_Packet( CR_(COL_PACKET,DIM) tgPacket, CR_(MATRIX,3,4) ptmM0 )
{
    PC_(COL_PACKET,DIM) ptgPacket = New_Packet();
    tgPacket.Transform( ptgPacket, ptmM0 );

    return (ptgPacket);
};


// ============================================================================================================================== //
// -- Geometry 3D - Generic Routines -------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

// ---- Calc_Support_Point ------------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
T_(VECTOR,DIM) TTgCOL_PACKET<TYPE,DIM>::Calc_Support_Point( M_(VECTOR,DIM) tvDirN ) const
{
    switch (Query_Primitive())
    {
        case ETgCIRCLE:         return (m_tgCI.Calc_Support_Point( tvDirN ));
        case ETgDISK:           return (m_tgDK.Calc_Support_Point( tvDirN ));
        case ETgELLIPSE:        return (m_tgEL.Calc_Support_Point( tvDirN ));
        case ETgPTRI:           return (m_tgPT.Calc_Support_Point( tvDirN ));
        case ETgETRI:           return (m_tgET.Calc_Support_Point( tvDirN ));
        case ETgCTRI:           return (m_tgCT.Calc_Support_Point( tvDirN ));
        case ETgSTRI:           return (m_tgST.Calc_Support_Point( tvDirN ));
        case ETgRECTANGLE:      return (m_tgRT.Calc_Support_Point( tvDirN ));
        case ETgPARALLELOGRAM:  return (m_tgPE.Calc_Support_Point( tvDirN ));
        case ETgSPHERE:         return (m_tgSP.Calc_Support_Point( tvDirN ));
        case ETgBOX:            return (m_tgBX.Calc_Support_Point( tvDirN ));
        case ETgBOXAA:          return (m_tgBA.Calc_Support_Point( tvDirN ));
        case ETgCAPSULE:        return (m_tgCP.Calc_Support_Point( tvDirN ));
        case ETgCYLINDER:       return (m_tgCY.Calc_Support_Point( tvDirN ));
        case ETgMESH_AABB:      return (m_tgMH.Calc_Support_Point( tvDirN ));

        default:                TgASSERT( TgFALSE ); return (MATH::F_0<TYPE,DIM>());
    };
};


// ---- Calc_Volume ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TYPE TTgCOL_PACKET<TYPE,DIM>::Calc_Volume() const
{
    switch (Query_Primitive())
    {
        case ETgSPHERE:         return (m_tgSP.Calc_Volume());
        case ETgBOX:            return (m_tgBX.Calc_Volume());
        case ETgBOXAA:          return (m_tgBA.Calc_Volume());
        case ETgCAPSULE:        return (m_tgCP.Calc_Volume());
        case ETgCYLINDER:       return (m_tgCY.Calc_Volume());
        case ETgMESH_AABB:      return (m_tgMH.Calc_Volume());

        default:                TgASSERT( TgFALSE ); return (TYPE(-1.0));
    };
};


// ---- Calc_Surface_Area ------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TYPE TTgCOL_PACKET<TYPE,DIM>::Calc_Surface_Area() const
{
    switch (Query_Primitive())
    {
        case ETgCIRCLE:         return (m_tgCI.Calc_Area());
        case ETgDISK:           return (m_tgDK.Calc_Area());
        case ETgELLIPSE:        return (m_tgEL.Calc_Area());
        case ETgPTRI:           return (m_tgPT.Calc_Area());
        case ETgETRI:           return (m_tgET.Calc_Area());
        case ETgCTRI:           return (m_tgCT.Calc_Area());
        case ETgSTRI:           return (m_tgST.Calc_Area());
        case ETgRECTANGLE:      return (m_tgRT.Calc_Area());
        case ETgPARALLELOGRAM:  return (m_tgPE.Calc_Area());
        case ETgSPHERE:         return (m_tgSP.Calc_Surface_Area());
        case ETgBOX:            return (m_tgBX.Calc_Surface_Area());
        case ETgBOXAA:          return (m_tgBA.Calc_Surface_Area());
        case ETgCAPSULE:        return (m_tgCP.Calc_Surface_Area());
        case ETgCYLINDER:       return (m_tgCY.Calc_Surface_Area());
        case ETgMESH_AABB:      return (m_tgMH.Calc_Surface_Area());

        default:                TgASSERT( TgFALSE ); return (TYPE(-1.0));
    };
};


// ---- Calc_AABB --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Calc_AABB( PC_(BOXAA,DIM) ptgBA0 ) const
{
    switch (Query_Primitive())
    {
        case ETgSEGMENT:        m_tgSG.Calc_AABB( ptgBA0 ); break;

        case ETgCIRCLE:         m_tgCI.Calc_AABB( ptgBA0 ); break;
        case ETgDISK:           m_tgDK.Calc_AABB( ptgBA0 ); break;
        case ETgELLIPSE:        m_tgEL.Calc_AABB( ptgBA0 ); break;
        case ETgPTRI:           m_tgPT.Calc_AABB( ptgBA0 ); break;
        case ETgETRI:           m_tgET.Calc_AABB( ptgBA0 ); break;
        case ETgCTRI:           m_tgCT.Calc_AABB( ptgBA0 ); break;
        case ETgSTRI:           m_tgST.Calc_AABB( ptgBA0 ); break;
        case ETgRECTANGLE:      m_tgRT.Calc_AABB( ptgBA0 ); break;
        case ETgPARALLELOGRAM:  m_tgPE.Calc_AABB( ptgBA0 ); break;
        case ETgSPHERE:         m_tgSP.Calc_AABB( ptgBA0 ); break;
        case ETgBOX:            m_tgBX.Calc_AABB( ptgBA0 ); break;
        case ETgBOXAA:          m_tgBA.Calc_AABB( ptgBA0 ); break;
        case ETgCAPSULE:        m_tgCP.Calc_AABB( ptgBA0 ); break;
        case ETgCYLINDER:       m_tgCY.Calc_AABB( ptgBA0 ); break;
        case ETgMESH_AABB:      m_tgMH.Calc_AABB( ptgBA0 ); break;

        default:                TgASSERT( TgFALSE ); ptgBA0->Set_Invalid(); break;
    };
};


// ---- Calc_AABB --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Calc_AABB( PC_(BOXAA,DIM) ptgBA0, M_(VECTOR,DIM) tvDT ) const
{
    switch (Query_Primitive())
    {
        case ETgSEGMENT:        m_tgSG.Calc_AABB( ptgBA0, tvDT ); break;

        case ETgCIRCLE:         m_tgCI.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgDISK:           m_tgDK.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgELLIPSE:        m_tgEL.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgPTRI:           m_tgPT.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgETRI:           m_tgET.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgCTRI:           m_tgCT.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgSTRI:           m_tgST.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgRECTANGLE:      m_tgRT.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgPARALLELOGRAM:  m_tgPE.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgSPHERE:         m_tgSP.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgBOX:            m_tgBX.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgBOXAA:          m_tgBA.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgCAPSULE:        m_tgCP.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgCYLINDER:       m_tgCY.Calc_AABB( ptgBA0, tvDT ); break;
        case ETgMESH_AABB:      m_tgMH.Calc_AABB( ptgBA0, tvDT ); break;

        default:                TgASSERT( TgFALSE ); ptgBA0->Set_Invalid(); break;
    };
};


// ---- Project ----------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Project( TYPE *ptyMin, TYPE *ptyMax, M_(VECTOR,DIM) tvAxis ) const
{
    switch (Query_Primitive())
    {
        case ETgPARTICLE:       m_tgPC.Project( ptyMin, ptyMax, tvAxis ); break;

        case ETgLINE:           m_tgLN.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgRAY:            m_tgRY.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgSEGMENT:        m_tgSG.Project( ptyMin, ptyMax, tvAxis ); break;

        case ETgCIRCLE:         m_tgCI.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgDISK:           m_tgDK.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgELLIPSE:        m_tgEL.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgPTRI:           m_tgPT.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgETRI:           m_tgET.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgCTRI:           m_tgCT.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgSTRI:           m_tgST.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgRECTANGLE:      m_tgRT.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgPARALLELOGRAM:  m_tgPE.Project( ptyMin, ptyMax, tvAxis ); break;

        case ETgSPHERE:         m_tgSP.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgBOX:            m_tgBX.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgBOXAA:          m_tgBA.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgCAPSULE:        m_tgCP.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgCYLINDER:       m_tgCY.Project( ptyMin, ptyMax, tvAxis ); break;
        case ETgMESH_AABB:      m_tgMH.Project( ptyMin, ptyMax, tvAxis ); break;

        default:                *ptyMin = LIMITS<TYPE>::MAX; *ptyMax = -LIMITS<TYPE>::MAX; TgASSERT( TgFALSE );
    };
};


// ---- Is_Contained ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgBOOL TTgCOL_PACKET<TYPE,DIM>::Is_Contained( M_(VECTOR,DIM) tvS0 ) const
{
    switch (Query_Primitive())
    {
        case ETgCIRCLE:         return (m_tgCI.Is_Contained( tvS0 ));
        case ETgDISK:           return (m_tgDK.Is_Contained( tvS0 ));
        case ETgELLIPSE:        return (m_tgEL.Is_Contained( tvS0 ));
        case ETgPTRI:           return (m_tgPT.Is_Contained( tvS0 ));
        case ETgETRI:           return (m_tgET.Is_Contained( tvS0 ));
        case ETgCTRI:           return (m_tgCT.Is_Contained( tvS0 ));
        case ETgSTRI:           return (m_tgST.Is_Contained( tvS0 ));
        case ETgRECTANGLE:      return (m_tgRT.Is_Contained( tvS0 ));
        case ETgPARALLELOGRAM:  return (m_tgPE.Is_Contained( tvS0 ));

        case ETgSPHERE:         return (m_tgSP.Is_Contained( tvS0 ));
        case ETgBOX:            return (m_tgBX.Is_Contained( tvS0 ));
        case ETgBOXAA:          return (m_tgBA.Is_Contained( tvS0 ));
        case ETgCAPSULE:        return (m_tgCP.Is_Contained( tvS0 ));
        case ETgCYLINDER:       return (m_tgCY.Is_Contained( tvS0 ));
        case ETgMESH_AABB:      return (m_tgMH.Is_Contained( tvS0 ));

        default:                TgASSERT( TgFALSE ); return (TgFALSE);
    };
};


// ============================================================================================================================== //
// -- Local -> New Reference Frame ---------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

// ---- Copy_Common ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Copy_Common( CR_(COL_PACKET,DIM) tgPacket )
{
    // Base configuration

    m_tgContext = tgPacket.m_tgContext;
    m_uiFilter_Objects = tgPacket.m_uiFilter_Objects;
    m_ptgMainObject = tgPacket.m_ptgMainObject;
    m_tgAABB = tgPacket.m_tgAABB;
    m_bfFlags = tgPacket.m_bfFlags;

    m_uiPrimitive = tgPacket.m_uiPrimitive;
    Set_Purpose( tgPacket.m_uiPurpose );

    // Copy filters

    m_niObject_Graph_Ignored = tgPacket.m_niObject_Graph_Ignored;

    for (int i=0; i < m_niObject_Graph_Ignored; ++i)
    {
        m_atgObject_Graph_Ignored[i] = tgPacket.m_atgObject_Graph_Ignored[i];
    };

    m_niObject_Ignored = tgPacket.m_niObject_Ignored;

    for (int i=0; i < m_niObject_Ignored; ++i)
    {
        m_atgObject_Ignored[i] = tgPacket.m_atgObject_Ignored[i];
    };

    m_niLiteral_Ignored = tgPacket.m_niLiteral_Ignored;

    for (int i=0; i < m_niLiteral_Ignored; ++i)
    {
        m_atgLiteral_Ignored[i] = tgPacket.m_atgLiteral_Ignored[i];
    };

    // Copy fourth dimensional data

    m_tyToI = tgPacket.m_tyToI;

    m_tgDT.m_tyDT = tgPacket.m_tgDT.m_tyDT;
    m_tgDT.m_tyDT_DT = tgPacket.m_tgDT.m_tyDT_DT;
    m_tgDT.m_tyInv_DT = tgPacket.m_tgDT.m_tyInv_DT;
    m_tgDT.m_tvDT = tgPacket.m_tgDT.m_tvDT;
    m_tgDT.m_tvUDT = tgPacket.m_tgDT.m_tvUDT;

    // Destructive copy of the results - resize result array upwards if necessary.

    if (m_niResult_End < tgPacket.m_niResult_End)
    {
        if (Query_OwnsData())
        {
            TgDELETE_ARRAY( m_ptgResult );
        };

        m_ptgResult = TgNEW T_(COL_RESULT,DIM)[tgPacket.m_niResult_End];
        m_niResult_End = tgPacket.m_niResult_End;

        Set_OwnsData( TgTRUE );
    };

    for (TgINT32 i=0; i < tgPacket.m_niResult_Last; ++i)
    {
        m_ptgResult[i] = tgPacket.m_ptgResult[i];
    };
    m_niResult_Last = tgPacket.m_niResult_Last;
};


// ---- Copy -------------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Set( CR_(COL_PACKET,DIM) tgPacket )
{
    Primitive_Reset();
    Copy_Common( tgPacket );

    TgASSERT(Query_Primitive() == tgPacket.Query_Primitive())
    switch (Query_Primitive()) {

    case ETgPARTICLE:       m_tgPC.Set( tgPacket.m_tgPC );

    case ETgLINE:           m_tgLN.Set( tgPacket.m_tgLN );
    case ETgRAY:            m_tgRY.Set( tgPacket.m_tgRY );
    case ETgSEGMENT:        m_tgSG.Set( tgPacket.m_tgSG );

    case ETgCIRCLE:         m_tgCI.Set( tgPacket.m_tgCI );
    case ETgDISK:           m_tgDK.Set( tgPacket.m_tgDK );
    case ETgELLIPSE:        m_tgEL.Set( tgPacket.m_tgEL );
    case ETgPTRI:           m_tgPT.Set( tgPacket.m_tgPT );
    case ETgETRI:           m_tgET.Set( tgPacket.m_tgET );
    case ETgCTRI:           m_tgCT.Set( tgPacket.m_tgCT );
    case ETgSTRI:           m_tgST.Set( tgPacket.m_tgST );
    case ETgRECTANGLE:      m_tgRT.Set( tgPacket.m_tgRT );
    case ETgPARALLELOGRAM:  m_tgPE.Set( tgPacket.m_tgPE );

    case ETgSPHERE:         m_tgSP.Set( tgPacket.m_tgSP );
    case ETgBOX:            m_tgBX.Set( tgPacket.m_tgBX );
    case ETgBOXAA:          m_tgBA.Set( tgPacket.m_tgBA );
    case ETgCAPSULE:        m_tgCP.Set( tgPacket.m_tgCP );
    case ETgCYLINDER:       m_tgCY.Set( tgPacket.m_tgCY );
    case ETgMESH_AABB:      m_tgMH.Set( tgPacket.m_tgMH );

    default: TgASSERT( TgFALSE );

    };
};


// ---- Transform --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Transform( CR_(MATRIX,3,4) ptmM0 )
{
    switch (Query_Primitive()) {

    case ETgPARTICLE:       m_tgPC.Transform( ptmM0 ); m_tgPC.Calc_AABB( &m_tgAABB ); break;
                                                                         
    case ETgLINE:           m_tgLN.Transform( ptmM0 ); m_tgLN.Calc_AABB( &m_tgAABB ); break;
    case ETgRAY:            m_tgRY.Transform( ptmM0 ); m_tgRY.Calc_AABB( &m_tgAABB ); break;
    case ETgSEGMENT:        m_tgSG.Transform( ptmM0 ); m_tgSG.Calc_AABB( &m_tgAABB ); break;
                                                                         
    case ETgCIRCLE:         m_tgCI.Transform( ptmM0 ); m_tgCI.Calc_AABB( &m_tgAABB ); break;
    case ETgDISK:           m_tgDK.Transform( ptmM0 ); m_tgDK.Calc_AABB( &m_tgAABB ); break;
    case ETgELLIPSE:        m_tgEL.Transform( ptmM0 ); m_tgEL.Calc_AABB( &m_tgAABB ); break;
    case ETgPTRI:           m_tgPT.Transform( ptmM0 ); m_tgPT.Calc_AABB( &m_tgAABB ); break;
    case ETgETRI:           m_tgET.Transform( ptmM0 ); m_tgET.Calc_AABB( &m_tgAABB ); break;
    case ETgCTRI:           m_tgCT.Transform( ptmM0 ); m_tgCT.Calc_AABB( &m_tgAABB ); break;
    case ETgSTRI:           m_tgST.Transform( ptmM0 ); m_tgST.Calc_AABB( &m_tgAABB ); break;
    case ETgRECTANGLE:      m_tgRT.Transform( ptmM0 ); m_tgRT.Calc_AABB( &m_tgAABB ); break;
    case ETgPARALLELOGRAM:  m_tgPE.Transform( ptmM0 ); m_tgPE.Calc_AABB( &m_tgAABB ); break;
                                                                         
    case ETgSPHERE:         m_tgSP.Transform( ptmM0 ); m_tgSP.Calc_AABB( &m_tgAABB ); break;
    case ETgBOX:            m_tgBX.Transform( ptmM0 ); m_tgBX.Calc_AABB( &m_tgAABB ); break;
    case ETgBOXAA:          m_tgBA.Transform( ptmM0 ); m_tgBA.Calc_AABB( &m_tgAABB ); break;
    case ETgCAPSULE:        m_tgCP.Transform( ptmM0 ); m_tgCP.Calc_AABB( &m_tgAABB ); break;
    case ETgCYLINDER:       m_tgCY.Transform( ptmM0 ); m_tgCY.Calc_AABB( &m_tgAABB ); break;
    case ETgMESH_AABB:      m_tgMH.Transform( ptmM0 ); m_tgMH.Calc_AABB( &m_tgAABB ); break;

    default: TgASSERT( TgFALSE );

    };

    m_tgDT.m_tvUDT = MATH::F_TX( ptmM0, m_tgDT.m_tvUDT );
    m_tgDT.m_tvDT = MATH::F_TX( ptmM0, m_tgDT.m_tvDT );

    if (0 != (m_uiTest & ETgTEST_SWEEP))
    {
        m_tgAABB.Sweep( MATH::F_MUL( Query_ToI(), Query_DT().m_tvDT ) );
    }

    for (TgINT32 i=0; i < m_niResult_Last; ++i)
    {
        m_ptgResult[i].Set_Position( MATH::F_TX( ptmM0, m_ptgResult[i].Query_Position() ) );
        m_ptgResult[i].Set_Normal( MATH::F_TX( ptmM0, m_ptgResult[i].Query_Normal() ) );
        m_ptgResult[i].Get_Tri().Transform( ptmM0 );
    };
};


// ---- Transform --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Transform( PC_(COL_PACKET,DIM) ptgPT, CR_(MATRIX,3,4) tmM0 ) const
{
    ptgPT->Primitive_Reset();
    ptgPT->Copy_Common( *this );
    TgASSERT(Query_Primitive() == ptgPT->Query_Primitive())

    switch (Query_Primitive()) {

    case ETgPARTICLE:       m_tgPC.Transform( ptgPT->m_tgPC, tmM0 ); ptgPT->m_tgPC.Calc_AABB( &ptgPT->m_tgAABB ); break;

    case ETgLINE:           m_tgLN.Transform( ptgPT->m_tgLN, tmM0 ); ptgPT->m_tgLN.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgRAY:            m_tgRY.Transform( ptgPT->m_tgRY, tmM0 ); ptgPT->m_tgRY.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgSEGMENT:        m_tgSG.Transform( ptgPT->m_tgSG, tmM0 ); ptgPT->m_tgSG.Calc_AABB( &ptgPT->m_tgAABB ); break;

    case ETgCIRCLE:         m_tgCI.Transform( ptgPT->m_tgCI, tmM0 ); ptgPT->m_tgCI.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgDISK:           m_tgDK.Transform( ptgPT->m_tgDK, tmM0 ); ptgPT->m_tgDK.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgELLIPSE:        m_tgEL.Transform( ptgPT->m_tgEL, tmM0 ); ptgPT->m_tgEL.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgPTRI:           m_tgPT.Transform( ptgPT->m_tgPT, tmM0 ); ptgPT->m_tgPT.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgETRI:           m_tgET.Transform( ptgPT->m_tgET, tmM0 ); ptgPT->m_tgET.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgCTRI:           m_tgCT.Transform( ptgPT->m_tgCT, tmM0 ); ptgPT->m_tgCT.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgSTRI:           m_tgST.Transform( ptgPT->m_tgST, tmM0 ); ptgPT->m_tgST.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgRECTANGLE:      m_tgRT.Transform( ptgPT->m_tgRT, tmM0 ); ptgPT->m_tgRT.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgPARALLELOGRAM:  m_tgPE.Transform( ptgPT->m_tgPE, tmM0 ); ptgPT->m_tgPE.Calc_AABB( &ptgPT->m_tgAABB ); break;

    case ETgSPHERE:         m_tgSP.Transform( ptgPT->m_tgSP, tmM0 ); ptgPT->m_tgSP.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgBOX:            m_tgBX.Transform( ptgPT->m_tgBX, tmM0 ); ptgPT->m_tgBX.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgBOXAA:          m_tgBA.Transform( ptgPT->m_tgBA, tmM0 ); ptgPT->m_tgBA.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgCAPSULE:        m_tgCP.Transform( ptgPT->m_tgCP, tmM0 ); ptgPT->m_tgCP.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgCYLINDER:       m_tgCY.Transform( ptgPT->m_tgCY, tmM0 ); ptgPT->m_tgCY.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgMESH_AABB:      m_tgMH.Transform( ptgPT->m_tgMH, tmM0 ); ptgPT->m_tgMH.Calc_AABB( &ptgPT->m_tgAABB ); break;

    default: TgASSERT( TgFALSE );

    };

    ptgPT->m_tgDT.m_tvUDT = MATH::F_TX( tmM0, m_tgDT.m_tvUDT );
    ptgPT->m_tgDT.m_tvDT = MATH::F_TX( tmM0, m_tgDT.m_tvDT );

    if (0 != (m_uiTest & ETgTEST_SWEEP))
    {
        ptgPT->m_tgAABB.Sweep( MATH::F_MUL( Query_ToI(), Query_DT().m_tvDT ) );
    }

    for (TgINT32 i=0; i < m_niResult_Last; ++i)
    {
        ptgPT->m_ptgResult[i].Set_Position( MATH::F_TX( tmM0, ptgPT->m_ptgResult[i].Query_Position() ) );
        ptgPT->m_ptgResult[i].Set_Normal( MATH::F_TX( tmM0, ptgPT->m_ptgResult[i].Query_Normal() ) );
        ptgPT->m_ptgResult[i].Get_Tri().Transform( tmM0 );
    };
};


// ---- VTX --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::VTX( CR_(MATRIX,3,4) tmM0 )
{
    switch (Query_Primitive()) {

    case ETgPARTICLE:       m_tgPC.VTX( tmM0 ); m_tgPC.Calc_AABB( &m_tgAABB ); break;
                                                                  
    case ETgLINE:           m_tgLN.VTX( tmM0 ); m_tgLN.Calc_AABB( &m_tgAABB ); break;
    case ETgRAY:            m_tgRY.VTX( tmM0 ); m_tgRY.Calc_AABB( &m_tgAABB ); break;
    case ETgSEGMENT:        m_tgSG.VTX( tmM0 ); m_tgSG.Calc_AABB( &m_tgAABB ); break;
                                                                  
    case ETgCIRCLE:         m_tgCI.VTX( tmM0 ); m_tgCI.Calc_AABB( &m_tgAABB ); break;
    case ETgDISK:           m_tgDK.VTX( tmM0 ); m_tgDK.Calc_AABB( &m_tgAABB ); break;
    case ETgELLIPSE:        m_tgEL.VTX( tmM0 ); m_tgEL.Calc_AABB( &m_tgAABB ); break;
    case ETgPTRI:           m_tgPT.VTX( tmM0 ); m_tgPT.Calc_AABB( &m_tgAABB ); break;
    case ETgETRI:           m_tgET.VTX( tmM0 ); m_tgET.Calc_AABB( &m_tgAABB ); break;
    case ETgCTRI:           m_tgCT.VTX( tmM0 ); m_tgCT.Calc_AABB( &m_tgAABB ); break;
    case ETgSTRI:           m_tgST.VTX( tmM0 ); m_tgST.Calc_AABB( &m_tgAABB ); break;
    case ETgRECTANGLE:      m_tgRT.VTX( tmM0 ); m_tgRT.Calc_AABB( &m_tgAABB ); break;
    case ETgPARALLELOGRAM:  m_tgPE.VTX( tmM0 ); m_tgPE.Calc_AABB( &m_tgAABB ); break;
                                                                  
    case ETgSPHERE:         m_tgSP.VTX( tmM0 ); m_tgSP.Calc_AABB( &m_tgAABB ); break;
    case ETgBOX:            m_tgBX.VTX( tmM0 ); m_tgBX.Calc_AABB( &m_tgAABB ); break;
//  case ETgBOXAA:          m_tgBA.VTX( tmM0 ); m_tgBA.Calc_AABB( &m_tgAABB ); break;
    case ETgCAPSULE:        m_tgCP.VTX( tmM0 ); m_tgCP.Calc_AABB( &m_tgAABB ); break;
    case ETgCYLINDER:       m_tgCY.VTX( tmM0 ); m_tgCY.Calc_AABB( &m_tgAABB ); break;
    case ETgMESH_AABB:      m_tgMH.VTX( tmM0 ); m_tgMH.Calc_AABB( &m_tgAABB ); break;

    default: TgASSERT( TgFALSE );

    };

    m_tgDT.m_tvUDT = MATH::M_TX( tmM0, m_tgDT.m_tvUDT );
    m_tgDT.m_tvDT = MATH::M_TX( tmM0, m_tgDT.m_tvDT );

    if (0 != (m_uiTest & ETgTEST_SWEEP))
    {
        m_tgAABB.Sweep( MATH::F_MUL( Query_ToI(), Query_DT().m_tvDT ) );
    }

    for (TgINT32 i=0; i < m_niResult_Last; ++i)
    {
        m_ptgResult[i].Set_Position( MATH::M_TX( tmM0, m_ptgResult[i].Query_Position() ) );
        m_ptgResult[i].Set_Normal( MATH::M_TX( tmM0, m_ptgResult[i].Query_Normal() ) );
        m_ptgResult[i].Get_Tri().VTX( tmM0 );
    };
};


// ---- VTX --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::VTX( PC_(COL_PACKET,DIM) ptgPT, CR_(MATRIX,3,4) tmM0 ) const
{
    ptgPT->Primitive_Reset();
    ptgPT->Copy_Common( *this );
    TgASSERT(Query_Primitive() == ptgPT->Query_Primitive())

    switch (Query_Primitive()) {

    case ETgPARTICLE:       m_tgPC.VTX( ptgPT->m_tgPC, tmM0 ); ptgPT->m_tgPC.Calc_AABB( &ptgPT->m_tgAABB ); break;
                                                                                        
    case ETgLINE:           m_tgLN.VTX( ptgPT->m_tgLN, tmM0 ); ptgPT->m_tgLN.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgRAY:            m_tgRY.VTX( ptgPT->m_tgRY, tmM0 ); ptgPT->m_tgRY.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgSEGMENT:        m_tgSG.VTX( ptgPT->m_tgSG, tmM0 ); ptgPT->m_tgSG.Calc_AABB( &ptgPT->m_tgAABB ); break;
                                                                                        
    case ETgCIRCLE:         m_tgCI.VTX( ptgPT->m_tgCI, tmM0 ); ptgPT->m_tgCI.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgDISK:           m_tgDK.VTX( ptgPT->m_tgDK, tmM0 ); ptgPT->m_tgDK.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgELLIPSE:        m_tgEL.VTX( ptgPT->m_tgEL, tmM0 ); ptgPT->m_tgEL.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgPTRI:           m_tgPT.VTX( ptgPT->m_tgPT, tmM0 ); ptgPT->m_tgPT.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgETRI:           m_tgET.VTX( ptgPT->m_tgET, tmM0 ); ptgPT->m_tgET.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgCTRI:           m_tgCT.VTX( ptgPT->m_tgCT, tmM0 ); ptgPT->m_tgCT.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgSTRI:           m_tgST.VTX( ptgPT->m_tgST, tmM0 ); ptgPT->m_tgST.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgRECTANGLE:      m_tgRT.VTX( ptgPT->m_tgRT, tmM0 ); ptgPT->m_tgRT.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgPARALLELOGRAM:  m_tgPE.VTX( ptgPT->m_tgPE, tmM0 ); ptgPT->m_tgPE.Calc_AABB( &ptgPT->m_tgAABB ); break;
                                                                                        
    case ETgSPHERE:         m_tgSP.VTX( ptgPT->m_tgSP, tmM0 ); ptgPT->m_tgSP.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgBOX:            m_tgBX.VTX( ptgPT->m_tgBX, tmM0 ); ptgPT->m_tgBX.Calc_AABB( &ptgPT->m_tgAABB ); break;
//  case ETgBOXAA:          m_tgBA.VTX( ptgPT->m_tgBA, tmM0 ); ptgPT->m_tgBA.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgCAPSULE:        m_tgCP.VTX( ptgPT->m_tgCP, tmM0 ); ptgPT->m_tgCP.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgCYLINDER:       m_tgCY.VTX( ptgPT->m_tgCY, tmM0 ); ptgPT->m_tgCY.Calc_AABB( &ptgPT->m_tgAABB ); break;
    case ETgMESH_AABB:      m_tgMH.VTX( ptgPT->m_tgMH, tmM0 ); ptgPT->m_tgMH.Calc_AABB( &ptgPT->m_tgAABB ); break;

    default: TgASSERT( TgFALSE );

    };

    ptgPT->m_tgDT.m_tvUDT = MATH::M_TX( tmM0, m_tgDT.m_tvUDT );
    ptgPT->m_tgDT.m_tvDT = MATH::M_TX( tmM0, m_tgDT.m_tvDT );

    if (0 != (m_uiTest & ETgTEST_SWEEP))
    {
        ptgPT->m_tgAABB.Sweep( MATH::F_MUL( Query_ToI(), Query_DT().m_tvDT ) );
    }

    for (TgINT32 i=0; i < m_niResult_Last; ++i)
    {
        ptgPT->m_ptgResult[i].Set_Position( MATH::M_TX( tmM0, ptgPT->m_ptgResult[i].Query_Position() ) );
        ptgPT->m_ptgResult[i].Set_Normal( MATH::M_TX( tmM0, ptgPT->m_ptgResult[i].Query_Normal() ) );
        ptgPT->m_ptgResult[i].Get_Tri().VTX( tmM0 );
    };
};


// ============================================================================================================================== //
// -- State Control ------------------------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

// ---- Update_ToI -------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Update_ToI( const TYPE tyToI )
{
    TgASSERT( tyToI >= 0.0F && MATH::Is_Valid( tyToI ) );

    m_tyToI = tyToI;
    Calc_AABB();
};


// ============================================================================================================================== //
// -- Intersection Control ------------------------------------------------------------------------------------------------------ //
// ============================================================================================================================== //





// ============================================================================================================================== //
// -- Ignore Control ------------------------------------------------------------------------------------------------------------ //
// ============================================================================================================================== //

// ---- Ignore_Object ----------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Ignore_Object( CPC_CTg2_Object ptgObject, C_TgBOOL bFlag )
{
    if (NULL == ptgObject)
    {
        return (TgE_FAIL);
    };

    // Check to see if the object is in the ignore list.

    for (TgINT iIdx = 0; iIdx < m_niObject_Ignored ; ++iIdx)
    {
        if (m_atgObject_Ignored[iIdx] != ptgObject)
        {
            continue;
        };

        if (!bFlag)
        {
            for (++iIdx; iIdx < m_niObject_Ignored ; ++iIdx)
            {
                m_atgObject_Ignored[iIdx] = m_atgObject_Ignored[iIdx-1];
            };
            --m_niObject_Ignored;
        };

        return (TgS_OK);
    };

    if (m_niObject_Ignored >= KTgNIgnoreMax || !bFlag)
    {
        return (TgE_FAIL);
    };

    m_atgObject_Ignored[m_niObject_Ignored++] = ptgObject;

    return (TgS_OK);
};


// ---- Ignore_Object_Tree ------------------------------------------------------------------------------------------------------ //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Ignore_Object_Tree( CPC_CTg2_Object ptgObject, C_TgBOOL bFlag )
{
    if (NULL == ptgObject)
    {
        return (TgE_FAIL);
    };

    // Check to see if the object is in the ignore list.

    for (TgINT iIdx = 0; iIdx < m_niObject_Graph_Ignored ; ++iIdx)
    {
        if (m_atgObject_Graph_Ignored[iIdx] != ptgObject)
        {
            continue;
        };

        if (!bFlag)
        {
            for (++iIdx; iIdx < m_niObject_Graph_Ignored ; ++iIdx)
            {
                m_atgObject_Graph_Ignored[iIdx] = m_atgObject_Graph_Ignored[iIdx-1];
            };
            --m_niObject_Graph_Ignored;
        };

        return (TgS_OK);
    };

    if (m_niObject_Graph_Ignored >= KTgNIgnoreMax || !bFlag)
    {
        return (TgE_FAIL);
    };

    m_atgObject_Graph_Ignored[m_niObject_Graph_Ignored++] = ptgObject;

    return (TgS_OK);
};


// ---- Ignore_Literal ---------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgRESULT TTgCOL_PACKET<TYPE,DIM>::Ignore_Literal( C_TgLITERAL tgLiteral, C_TgBOOL bFlag )
{
    if (TgLITERAL(ETgLITERAL_NONE) == tgLiteral)
    {
        return (TgE_FAIL);
    };

    // Check to see if the object is in the ignore list.

    for (TgINT iIdx = 0; iIdx < m_niLiteral_Ignored ; ++iIdx)
    {
        if (m_atgLiteral_Ignored[iIdx] != tgLiteral)
        {
            continue;
        };

        if (!bFlag)
        {
            for (++iIdx; iIdx < m_niLiteral_Ignored ; ++iIdx)
            {
                m_atgLiteral_Ignored[iIdx] = m_atgLiteral_Ignored[iIdx-1];
            };
            --m_niLiteral_Ignored;
        };

        return (TgS_OK);
    };

    if (m_niLiteral_Ignored >= KTgNIgnoreMax || !bFlag)
    {
        return (TgE_FAIL);
    };

    m_atgLiteral_Ignored[m_niLiteral_Ignored++] = tgLiteral;

    return (TgS_OK);
};


// ---- IsIgnored_Object -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgBOOL TTgCOL_PACKET<TYPE,DIM>::IsIgnored_Object( CPC_CTg2_Object ptgObject ) const
{
    TgASSERT( NULL != ptgObject );

    // Check to see if all objects are being ignored.

    if (IsIgnored_All())
    {
        return (TgTRUE);
    };

    // Check to see if the object is in the ignore list.

    for (TgINT iIdx = 0; iIdx < m_niObject_Ignored ; ++iIdx)
    {
        if (m_atgObject_Ignored[iIdx] == ptgObject)
        {
            return (TgTRUE);
        };
    };

    // Not ignored.

    return (TgFALSE); 
};


// ---- IsIgnored_Object -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgBOOL TTgCOL_PACKET<TYPE,DIM>::IsIgnored_Literal( C_TgLITERAL tgLiteral ) const
{
    TgASSERT( TgLITERAL(ETgLITERAL_NONE) != tgLiteral );

    // Check to see if all objects are being ignored.

    if (IsIgnored_All())
    {
        return (TgTRUE);
    };

    // Check to see if the object is in the ignore list.

    for (TgINT iIdx = 0; iIdx < m_niLiteral_Ignored ; ++iIdx)
    {
        if (m_atgLiteral_Ignored[iIdx] == tgLiteral)
        {
            return (TgTRUE);
        };
    };

    // Not ignored.

    return (TgFALSE); 
};


// ============================================================================================================================== //
// ---- Data Accessors ---------------------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

// ---- Set_Delta --------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Set_Delta( M_(VECTOR,DIM) tvDelta )
{
    m_tgDT.m_tvUDT = MATH::F_NORM( &m_tgDT.m_tyDT, tvDelta );
    m_tgDT.m_tvDT = tvDelta;

    if (m_tgDT.m_tyDT < LIMITS<TYPE>::EPSILON)
    {
        m_tgDT.m_tvUDT = MATH::F_0<TYPE,DIM>();
        m_tgDT.m_tvDT = MATH::F_0<TYPE,DIM>();

        m_tgDT.m_tyDT = TYPE(0.0);
        m_tgDT.m_tyInv_DT = TYPE(0.0);
        m_tgDT.m_tyDT_DT = TYPE(0.0);
    }
    else
    {
        m_tgDT.m_tyDT_DT= m_tgDT.m_tyDT * m_tgDT.m_tyDT;
        m_tgDT.m_tyInv_DT = TYPE(1.0) / m_tgDT.m_tyDT;
    }
};


// ============================================================================================================================== //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
// ============================================================================================================================== //
// ---- Next_Result ------------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
PC_(COL_RESULT,DIM) TTgCOL_PACKET<TYPE,DIM>::Next_Result( M_(VECTOR,DIM) tvPos, M_(VECTOR,DIM) tvNormal, const TYPE tyValue )
{
    for (TgINT32 niCount = 0; niCount < m_niResult_Last; ++niCount)
    {
        if (MATH::F_LSQ( MATH::F_SUB( tvPos, m_ptgResult[niCount].Query_Position() ) ) > LIMITS<TYPE>::ROOTEPSILON)
        {
            continue;
        };

        if (MATH::F_LSQ( MATH::F_SUB( tvNormal, m_ptgResult[niCount].Query_Normal() ) ) > LIMITS<TYPE>::ROOTEPSILON)
        {
            continue;
        };

        return (m_ptgResult + niCount);
    };

    if (m_niResult_Last < m_niResult_End)
    {
        return (m_ptgResult + m_niResult_Last++);
    };

    if (m_bfFlags.Query_Flag( ETg_FLAGS_NOSORT ))
    {
        return (NULL);
    };

    if (m_bfFlags.Query_Flag( ETg_FLAGS_ORDER_PARAMETER ))
    {
        // When sorting on depth, find the value closest to zero, and replace that entry.

        TYPE                                tyTMP = m_ptgResult[0].Query_Depth();
        TgINT32                             niCurrent = 0;

        for (TgINT32 niCount = 1; niCount < m_niResult_End; ++niCount)
        {
            if (tyTMP > m_ptgResult[niCount].Query_Depth())
            {
                tyTMP = m_ptgResult[niCount].Query_Depth();
                niCurrent = niCount;
            };
        };

        return (tyTMP > tyValue ? NULL : m_ptgResult + niCurrent);
    }
    else
    {
        // When sorting on time, find the value furthest from zero, and replace that entry.

        TYPE                                tyTMP = m_ptgResult[0].Query_FirstT();
        TgINT32                             niCurrent = 0;

        for (TgINT32 niCount = 1; niCount < m_niResult_End; ++niCount)
        {
            if (tyTMP < m_ptgResult[niCount].Query_FirstT())
            {
                tyTMP = m_ptgResult[niCount].Query_FirstT();
                niCurrent = niCount;
            };
        };

        return (tyTMP < tyValue ? NULL : m_ptgResult + niCurrent);
    };
};


// ============================================================================================================================== //
// -- Data Calculation ---------------------------------------------------------------------------------------------------------- //
// ============================================================================================================================== //

// ---- Primitive_Reset --------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Primitive_Reset()
{
    // Clear the current primitive
    switch (Query_Primitive()) {

    case ETgPARTICLE:       m_tgPC.Reset();

    case ETgLINE:           m_tgLN.Reset();
    case ETgRAY:            m_tgRY.Reset();
    case ETgSEGMENT:        m_tgSG.Reset();

    case ETgCIRCLE:         m_tgCI.Reset();
    case ETgDISK:           m_tgDK.Reset();
    case ETgELLIPSE:        m_tgEL.Reset();
    case ETgPTRI:           m_tgPT.Reset();
    case ETgETRI:           m_tgET.Reset();
    case ETgCTRI:           m_tgCT.Reset();
    case ETgSTRI:           m_tgST.Reset();
    case ETgRECTANGLE:      m_tgRT.Reset();
    case ETgPARALLELOGRAM:  m_tgPE.Reset();

    case ETgSPHERE:         m_tgSP.Reset();
    case ETgBOX:            m_tgBX.Reset();
    case ETgBOXAA:          m_tgBA.Reset();
    case ETgCAPSULE:        m_tgCP.Reset();
    case ETgCYLINDER:       m_tgCY.Reset();
    case ETgMESH_AABB:      m_tgMH.Reset();

    default: TgASSERT( TgFALSE );

    };
};


// ---- Calc_AABB -------------------------------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------------------------------------------------------ //

template <typename TYPE, int DIM>
TgVOID TTgCOL_PACKET<TYPE,DIM>::Calc_AABB()
{
    switch (Query_Primitive() + (m_uiTest << 16)) {

    case ETgPARTICLE + (ETgTEST_INTERSECT << 16):       Calc_AABB( &m_tgAABB ); break;

    case ETgLINE + (ETgTEST_INTERSECT << 16):           Calc_AABB( &m_tgAABB ); break;
    case ETgRAY + (ETgTEST_INTERSECT << 16):            Calc_AABB( &m_tgAABB ); break;
    case ETgSEGMENT + (ETgTEST_INTERSECT << 16):        Calc_AABB( &m_tgAABB ); break;

    case ETgCIRCLE + (ETgTEST_INTERSECT << 16):         Calc_AABB( &m_tgAABB ); break;
    case ETgDISK + (ETgTEST_INTERSECT << 16):           Calc_AABB( &m_tgAABB ); break;
    case ETgELLIPSE + (ETgTEST_INTERSECT << 16):        Calc_AABB( &m_tgAABB ); break;
    case ETgPTRI + (ETgTEST_INTERSECT << 16):           Calc_AABB( &m_tgAABB ); break;
    case ETgETRI + (ETgTEST_INTERSECT << 16):           Calc_AABB( &m_tgAABB ); break;
    case ETgCTRI + (ETgTEST_INTERSECT << 16):           Calc_AABB( &m_tgAABB ); break;
    case ETgSTRI + (ETgTEST_INTERSECT << 16):           Calc_AABB( &m_tgAABB ); break;
    case ETgRECTANGLE + (ETgTEST_INTERSECT << 16):      Calc_AABB( &m_tgAABB ); break;
    case ETgPARALLELOGRAM + (ETgTEST_INTERSECT << 16):  Calc_AABB( &m_tgAABB ); break;

    case ETgSPHERE + (ETgTEST_SWEEP_PENETRATE << 16):   Calc_AABB( &m_tgAABB, MATH::F_MUL( Query_ToI(), m_tgDT.m_tvDT ) ); break;
    case ETgSPHERE + (ETgTEST_SWEEP << 16):             Calc_AABB( &m_tgAABB, MATH::F_MUL( Query_ToI(), m_tgDT.m_tvDT ) ); break;
    case ETgSPHERE + (ETgTEST_INTERSECT << 16):         Calc_AABB( &m_tgAABB ); break;
    case ETgBOX + (ETgTEST_INTERSECT << 16):            Calc_AABB( &m_tgAABB ); break;
    case ETgBOXAA + (ETgTEST_INTERSECT << 16):          Calc_AABB( &m_tgAABB ); break;
    case ETgCAPSULE + (ETgTEST_INTERSECT << 16):        Calc_AABB( &m_tgAABB ); break;
    case ETgCYLINDER + (ETgTEST_INTERSECT << 16):       Calc_AABB( &m_tgAABB ); break;
    case ETgMESH_AABB + (ETgTEST_INTERSECT << 16):      Calc_AABB( &m_tgAABB ); break;

    default: TgASSERT( TgFALSE ); m_tgAABB.Set_Invalid(); break;

    };
};


// ============================================================================================================================== //

#if defined(TgS_INSTANTIATE_TEMPLATES)

    template class TTgCOL_PACKET<TgFLOAT32,4>;

#endif // TgS_INSTANTIATE_TEMPLATES

// ============================================================================================================================== //

}; // END COL //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}; // END TGS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////